
from simulation import run_simulation , frameAlohaSimulate
import sys
import settings
from reader import BinaryTagReader, GenOneTagReader,PureAlohaTagReader , FrameSlottedAlohaTagReader,LC_DFSATagReader , DTS_DFSATagReader

from tag import BaseTag, PureAlohaTag , FrameSlottedAlohaTag

from settings import logger
from plotter import Plot, MultiPlot
import matplotlib.pyplot as plt

import numpy as np

import time

# Utilitiy for printing the header
def print_header(text):
    logger.info("#"*(len(text)+5))
    logger.info(f"# {text}  #")
    logger.info("#"*(len(text)+5))


def execute(name, title, reader_cls,tag_cls, plot_index, colour=settings.GRAPH_COLOURS[0], iterations=settings.TEST_ITERATIONS):
    '''
    Run a specified simulation and get the average of the output across iterations
    '''
    y_sum     = [0] * len(settings.SAMPLE_SIZES) # Pre-fill with zeroes
    shift_sum = [0] * len(settings.SAMPLE_SIZES) # Pre-fill with zeroes
    mul_sum   = [0] * len(settings.SAMPLE_SIZES) # Pre-fill with zeroes
    div_sum   = [0] * len(settings.SAMPLE_SIZES) # Pre-fill with zeroes
    index_sum = [0] * len(settings.SAMPLE_SIZES) # Pre-fill with zeroes

    print_header(name)
    #循环十次，十次之后取平均，为了让相同标签使用的时隙数更加准确
    for _ in range(iterations):
        # y values for each iteration
        y = []
        runTime = []
        #每次循环都是执行一遍设定的标签数的防碰撞模拟
        for i, s in enumerate(settings.SAMPLE_SIZES):
            
            startTime = time.perf_counter()
            #_, num_slots = run_simulation(num_tags=s, reader_cls=reader_cls ,tag_cls=tag_cls) #模拟阅读器读标签
            _, num_slots ,shift_count, mul_count, div_count,index_count = frameAlohaSimulate(num_tags=s, reader_cls=reader_cls ,tag_cls=tag_cls) #模拟阅读器读标签
            
            y.append(num_slots)

            runTime[i] += time.perf_counter() - startTime
            # Get the average number of slots across all iterations
            y_sum[i] += (num_slots)

            shift_sum[i] += (shift_count)
            mul_sum[i] += (mul_count)
            div_sum[i] += (div_count)
            index_sum[i] += (index_count)
    runTime_Avg = list(map(lambda runTime: runTime/iterations, runTime))

    y_avg       = list(map(lambda y: y/iterations, y_sum))
    shift_avg   = list(map(lambda y: y/iterations, shift_sum))
    mul_avg     = list(map(lambda y: y/iterations, mul_sum))
    div_avg     = list(map(lambda y: y/iterations, div_sum))
    index_avg   = list(map(lambda y: y/iterations, index_sum))
    
    operator_avgs = {
    'shift_avg': shift_avg,
    'mul_avg': mul_avg,
    'div_avg': div_avg,
    'index_avg': index_avg
    }

    for tags in settings.SAMPLE_SIZES:
        log_items = [f"Tags: {tags}"]
        for name, avg_list in operator_avgs.items():
            log_items.append(f"{name}: {avg_list[settings.SAMPLE_SIZES.index(tags)]}")
        logger.info('\t'.join(log_items))

    efficiency_avg = []
    for tags, slots in zip(settings.SAMPLE_SIZES, y_avg):
        eff = tags / slots *100 # 计算效率单位%
        efficiency_avg.append(eff)
        logger.info(f"Tags: {tags}\t Total Slots: {slots}\tefficiency:{tags/slots*100:.4f}%")

    # --------- 新增部分：用matplotlib单独画效率曲线，正方形 ---------
    plt.plot(settings.SAMPLE_SIZES, efficiency_avg, marker='o',  label=f"{name}")

    
# Debug mode for a small sample
if len(sys.argv) > 1 and sys.argv [-1] == '--debug':
    print_header("BINARY DEBUG SIMULATION")
    run_simulation()
    exit(0)


# Configure which simulation to run
SIMULATIONS = [
    #{
    #    "name": "GEN 1 PROTOCOL",
    #    "title": "Gen 1 Protocol",
    #    "reader_cls": GenOneTagReader,
    #    "tag_cls": BaseTag
    #},
    #{
    #    "name": "BINARY TREE",
    #    "title": "Binary Tree Protocol",
    #    "reader_cls": BinaryTagReader,
    #    "tag_cls": BaseTag
    #},
    #{
    #    "name": "PURE ALOHA",
    #    "title": "Pure Aloha Protocol",
    #   "reader_cls": PureAlohaTagReader,
    #   "tag_cls": PureAlohaTag
    #},
    #{
    #    "name": "FRAME SLOTTE ALOHA",
    #    "title": "Frame slotted Aloha Protocol",
    #    "reader_cls": FrameSlottedAlohaTagReader,
    #    "tag_cls": FrameSlottedAlohaTag
    #},
    {
        "name": "LC_DFSA",
        "title": "LC_DFSA Protocol",
        "reader_cls": LC_DFSATagReader,
        "tag_cls": FrameSlottedAlohaTag
    },
    {
        "name": "DTS_DFSA",
        "title": "DTS_DFSA Protocol",
        "reader_cls": DTS_DFSATagReader,
        "tag_cls": FrameSlottedAlohaTag
    }
]

# plots = MultiPlot()
plots = MultiPlot(num_plots=(len(SIMULATIONS)+1))


#plots.set_meta(1, title="NFC Collision Algorithm Comparison", y_label="slots", x_label="tags")

# Run the simulations specified
plt.figure(1,figsize=(6,6))  # 正方形画布1
plt.xlabel("Tags")
plt.ylabel("Efficiency (%)")
plt.title(f"Efficiency Curve")
 
for index_sum, s in enumerate(SIMULATIONS):
    #execute(name, title, reader_cls, plot_index, colour=settings.GRAPH_COLOURS[0], iterations=settings.TEST_ITERATIONS):
    #**s，这是将字典s展开为关键字参数。
    plt.figure(1,figsize=(6,6))  # 正方形画布1

    #execute(**s, plot_index=index_sum+2, colour=settings.GRAPH_COLOURS[index_sum])
    execute(**s, plot_index=index_sum+2, colour=settings.GRAPH_COLOURS[index_sum])
plt.legend()
plt.grid(True)
plt.tight_layout()
#plt.show()
##############################
# Research paper data
##############################
#print_header("Research Paper")
#x = []
#y = []
#for x_p,y_p in settings.PAPER_BINARY_PROTOCOL_DATA:
#    x.append(x_p)
#    y.append(y_p)
#    print(f"Tags: {x_p}\t Total Slots: {y_p}")
#
#plots.add(x, y, 1, settings.GRAPH_COLOURS[2], label="Research Paper Binary Protocol")
#
#plots.show()
